#include "bsp_i2c.h"
#include "bsp_interrupt.h"
//#define AUTOACK

__WEAK void bsp_I2C1_Port_Init(void)
{
	PORT_SetFunc(I2C1_SCL_PORT, I2C1_SCL_Pin, I2C1_SCL_FUN, Disable);
    PORT_SetFunc(I2C1_SDA_PORT, I2C1_SDA_Pin, I2C1_SDA_FUN, Disable);
}
__WEAK void bsp_I2C2_Port_Init(void)
{
    PORT_SetFunc(I2C2_SCL_PORT, I2C2_SCL_Pin, I2C2_SCL_FUN, Disable);
    PORT_SetFunc(I2C2_SDA_PORT, I2C2_SDA_Pin, I2C2_SDA_FUN, Disable);
}
__WEAK void bsp_I2C3_Port_Init(void)
{
    ;
}
static void bsp_i2C_error_callback(void)
{
    if((Set == I2C_GetStatus(I2C1_UNIT, I2C_SR_TMOUTF))&&(I2C1_UNIT->CR2_f.TMOUTIE == 1))
    {
        I2C_SoftwareResetCmd(I2C1_UNIT,Enable);
        I2C_SoftwareResetCmd(I2C1_UNIT,Disable);
    }   
}
uint8_t  bsp_I2C_Init(M4_I2C_TypeDef* pstcI2Cx,uint32_t baudrate)
{
	stc_clk_freq_t freq_clk;
	stc_i2c_init_t stcI2cInit;
    stc_clock_timeout_init_t i2c_timerout_cfg;
    stc_irq_regi_conf_t stcIrqRegiConf;
    MEM_ZERO_STRUCT(i2c_timerout_cfg);
    float32_t fErr;		
	CLK_GetClockFreq(&freq_clk);	
	if(pstcI2Cx == I2C1_UNIT)
	{
		PWC_Fcg1PeriphClockCmd(I2C1_CLK,Enable);
        bsp_I2C1_Port_Init();
	}
	else if(pstcI2Cx == I2C2_UNIT)
	{
		PWC_Fcg1PeriphClockCmd(I2C2_CLK,Enable);
        bsp_I2C2_Port_Init();
	}
	else if(pstcI2Cx == I2C3_UNIT)
	{
		PWC_Fcg1PeriphClockCmd(I2C3_CLK,Enable);
        bsp_I2C3_Port_Init();
	}
	else
	{
		return 1;
	}
//    I2C_DeInit(pstcI2Cx);//冗余，I2C_Init里有相同操作。
    
    MEM_ZERO_STRUCT(stcI2cInit);
    stcI2cInit.u32Baudrate = baudrate;
	stcI2cInit.u32ClockDiv = I2C_CLK_DIV4;
    stcI2cInit.u32SclTime = 0;
    I2C_Init(pstcI2Cx, &stcI2cInit, &fErr);    
    I2C_Cmd(pstcI2Cx, Enable);
    
    i2c_timerout_cfg.enClkTimeOutSwitch = LowTimerOutOn;//开启I2C时钟低电平超时检测
    i2c_timerout_cfg.u16TimeOutHigh = 0xFFFF;
    i2c_timerout_cfg.u16TimeOutLow = 0xFFFF;//超时时间65535个I2C基准时钟(例程是42MHZ PCLK3),大概1.56ms时间
    I2C_ClkTimeOutConfig(I2C1_UNIT,&i2c_timerout_cfg);
    I2C_IntCmd(I2C1_UNIT,I2C_CR2_TMOURIE,Enable);
    stcIrqRegiConf.enIRQn = I2C1_EEI_IRQn;
    /* Select I2C Error or Event interrupt function */
    stcIrqRegiConf.enIntSrc = INT_I2C1_EEI;
    /* Callback function */
    stcIrqRegiConf.pfnCallback = &bsp_i2C_error_callback;
    /* Registration IRQ */
    enIrqRegistration(&stcIrqRegiConf);
    /* Clear Pending */
    NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
    /* Set priority */
    NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_15);
    /* Enable NVIC */
    NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
	return 0;
}
static inline uint8_t bsp_i2c_start(M4_I2C_TypeDef* pstcI2Cx)
{
    uint32_t u32TimeOut;
    I2C_GenerateStart(pstcI2Cx , Enable);
	u32TimeOut = TIMEOUT;
	while(Reset == I2C_GetStatus(pstcI2Cx, I2C_SR_TEMPTYF))//数据寄存器为空
	{
		if(0==u32TimeOut--)
		{
			if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
			{
				I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
			}			
			return I2C_TIMEROUT;
		}
	}
    return I2C_RET_OK;
}
static inline uint8_t bsp_i2c_sendonebyte(M4_I2C_TypeDef* pstcI2Cx, uint8_t data)
{
    uint32_t u32TimeOut;
    I2C_WriteData(pstcI2Cx, data);
    u32TimeOut = TIMEOUT;
    while(Reset == I2C_GetStatus(pstcI2Cx, I2C_SR_TENDF))//数据寄存器为空
    {
        if(0==(u32TimeOut--))
        {
            if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
            {
                I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
            }			
            return I2C_TIMEROUT;
        }
    }	
    u32TimeOut = TIMEOUT;
    while(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_NACKF))//等待应答
    {
        if(0 == (u32TimeOut--)) 
        {
            if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
            {
                I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
            }			
            return I2C_TIMEROUT;
        }
    }
    return I2C_RET_OK;	
}
static inline uint8_t bsp_i2c_senddevaddr(M4_I2C_TypeDef* pstcI2Cx, uint8_t devaddr)
{
    uint32_t u32TimeOut;
    I2C_WriteData(pstcI2Cx, devaddr);
    if((devaddr & 0x01) == 0)//读指令不检查TENDF
    {
        u32TimeOut = TIMEOUT;
        while(Reset == I2C_GetStatus(pstcI2Cx, I2C_SR_TENDF))//数据寄存器为空
        {
            if(0==(u32TimeOut--))
            {
                if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
                {
                    I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
                }			
                return I2C_TIMEROUT;
            }
        }
    }
    else{
        u32TimeOut = TIMEOUT;
        while(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_TRA))//等待转换为读状态，修复读指令从机回NAK，没有stop的问题。
        {
            if(0==(u32TimeOut--))
            {
                if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
                {
                    I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
                }			
                return I2C_TIMEROUT;
            }
        }
    }
    u32TimeOut = TIMEOUT;
    while(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_NACKF))//等待应答
    {
        if(0 == (u32TimeOut--)) 
        {
            if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
            {
                I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
            }			
            return I2C_TIMEROUT;
        }
    }
    return I2C_RET_OK;	
}
/*
ack = 0 回ACK， ack != 0 回NAK
*/
static inline uint8_t bsp_i2c_readonebyte(M4_I2C_TypeDef* pstcI2Cx, uint8_t *data, uint8_t ack)
{
    uint32_t u32TimeOut;
    u32TimeOut = TIMEOUT;
    while(Reset == I2C_GetStatus(pstcI2Cx, I2C_SR_RFULLF))
    {
        if(0 == (u32TimeOut--))
        {
            I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
            return I2C_TIMEROUT;
        }
    }
#ifndef AUTOACK			
    if(ack)
    {
        I2C_AckConfig(pstcI2Cx, I2c_NACK);
    }
    else
    {
        I2C_AckConfig(pstcI2Cx, I2c_ACK);//ACK
    }
#endif	        
    *data = pstcI2Cx->DRR_f.DR;//I2C_ReadData(I2C1_UNIT);
#ifdef AUTOACK			
    if(ack)
    {
        I2C_AckConfig(pstcI2Cx, I2c_NACK);//NAK
    }
    else
    {
        I2C_AckConfig(pstcI2Cx, I2c_ACK);//ACK
    }
#endif
    return I2C_RET_OK;
}
static inline uint8_t bsp_i2c_senddata(M4_I2C_TypeDef* pstcI2Cx,const uint8_t *data, uint16_t len)
{
	uint16_t pos;
    uint8_t status;
    for(pos = 0;pos<len;pos++)
	{
		status = bsp_i2c_sendonebyte(pstcI2Cx,data[pos]);
        if(status != I2C_RET_OK)
        {
            return status;
        }
	}
    return I2C_RET_OK;
}
static inline uint8_t bsp_i2c_Recdata(M4_I2C_TypeDef* pstcI2Cx,uint8_t *data, uint16_t len)
{
    uint8_t status;
	uint16_t pos;
    for(pos = 0;pos<len;pos++)
	{
        status = bsp_i2c_readonebyte(pstcI2Cx,data,(pos == (len-1)));
        if(status != I2C_RET_OK)
        {
            return status;
        }        
	}
    return I2C_RET_OK;
}
static inline uint8_t bsp_i2c_restart(M4_I2C_TypeDef* pstcI2Cx)
{
    uint32_t u32TimeOut;
    I2C_ClearStatus(pstcI2Cx, I2C_CLR_STARTFCLR);
	I2C_GenerateReStart(pstcI2Cx , Enable);//发送Restart;
	u32TimeOut = TIMEOUT;
	while((Reset == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY)) ||
            (Reset == I2C_GetStatus(pstcI2Cx, I2C_SR_STARTF)))
    {
        if(0 == (u32TimeOut--)) 
		{
			I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
			return I2C_RET_ERROR;
		}
    }
	u32TimeOut = TIMEOUT;
	while(Reset == I2C_GetStatus(pstcI2Cx, I2C_SR_TEMPTYF))//数据寄存器为空
	{
		if(0==u32TimeOut--)
		{
			if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
			{
				I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
			}			
			return I2C_TIMEROUT;
		}
	}
    return I2C_RET_OK;
}
static inline uint8_t bsp_i2c_stop(M4_I2C_TypeDef* pstcI2Cx)
{
    uint32_t u32TimeOut;
    u32TimeOut = TIMEOUT;
	do{
		I2C_GenerateStop(pstcI2Cx, Enable);//产生停止位
		if(0 == (u32TimeOut--)) 
			{
				return I2C_TIMEROUT;
			}
	}while(Reset == I2C_GetStatus(pstcI2Cx, I2C_SR_STOPF));//等待停止
    return I2C_RET_OK;
}
inline uint8_t bsp_i2c_resetbus(M4_I2C_TypeDef* pstcI2Cx)
{
    pstcI2Cx->CR1_f.SWRST = 1;
    pstcI2Cx->CR1_f.SWRST = 0;
    return I2C_RET_OK;
}
inline uint8_t I2C_Write_data(M4_I2C_TypeDef* pstcI2Cx,uint8_t DeviceAddr,uint8_t *addr, uint8_t addrsize, const uint8_t *data, uint16_t len)
{
    uint8_t status;	
    if(len == 0)
    {
        return I2C_BADPARA;
    }
    if(addrsize == 0)
    {
        return I2C_BADPARA;
    }
	if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))//多任务通信时，抢占总线判断
	{
        
		return I2C_BUSY;
	}
    if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_NACKF))//启动I2C前先清除上一次读写失败的NAK标志，否则无法写数据，多任务抢占时，不能加这一段
    {
        I2C_ClearStatus(pstcI2Cx,I2C_CLR_NACKFCLR);
    }
    status = bsp_i2c_start(pstcI2Cx);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	status = bsp_i2c_senddevaddr(pstcI2Cx,DeviceAddr<<1);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_senddata(pstcI2Cx,addr,addrsize);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	status = bsp_i2c_senddata(pstcI2Cx,data,len);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_stop(pstcI2Cx);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	return I2C_RET_OK;
}

inline uint8_t I2C_Read_data(M4_I2C_TypeDef* pstcI2Cx,uint8_t DeviceAddr,uint8_t *addr, uint8_t addrsize, uint8_t *data, uint16_t len)
{
	uint8_t status;	
    if(len == 0)
    {
        return I2C_BADPARA;
    }
    if(addrsize == 0)
    {
        return I2C_BADPARA;
    }
    if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
	{
		return I2C_BUSY;
	}	
    if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_NACKF))//启动I2C前先清除上一次读写失败的NAK标志，否则无法写数据
	{
		I2C_ClearStatus(pstcI2Cx,I2C_CLR_NACKFCLR);
	}
    status = bsp_i2c_start(pstcI2Cx);
#ifndef AUTOACK	
	pstcI2Cx->CR3_f.FACKEN = 1;//非自动写ACK
#endif	
    if(status != I2C_RET_OK)
    {
        return status;
    }
	status = bsp_i2c_senddevaddr(pstcI2Cx,DeviceAddr<<1);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_senddata(pstcI2Cx,addr,addrsize);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_restart(pstcI2Cx);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	status = bsp_i2c_senddevaddr(pstcI2Cx,(DeviceAddr<<1)|0x01);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_Recdata(pstcI2Cx,data,len);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_stop(pstcI2Cx);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	return I2C_RET_OK;
}
inline uint8_t I2C_Write_Buffer(M4_I2C_TypeDef* pstcI2Cx,uint8_t DeviceAddr,const uint8_t *data, uint16_t len)
{
    uint8_t status;
	if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
	{
		if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_ARLOF))//仲裁失败
		{
//			I2C_ClearStatus(I2C_CH, I2C_CLR_ARLOFCLR);
			pstcI2Cx->CLR = 0xFFFF;
			I2C_GenerateStop(pstcI2Cx, Enable);//停止释放总线
		}
		return I2C_BUSY;
	}
    if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_NACKF))//启动I2C前先清除上一次读写失败的NAK标志，否则无法写数据
	{
		I2C_ClearStatus(pstcI2Cx,I2C_CLR_NACKFCLR);
	}
	 status = bsp_i2c_start(pstcI2Cx);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	status = bsp_i2c_senddevaddr(pstcI2Cx,DeviceAddr<<1);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	status = bsp_i2c_senddata(pstcI2Cx,data,len);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_stop(pstcI2Cx);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	return I2C_RET_OK;
}
inline uint8_t I2C_Read_Buffer(M4_I2C_TypeDef* pstcI2Cx,uint8_t DeviceAddr, uint8_t *data, uint16_t len)
{
//	uint32_t u32TimeOut;
//	uint8_t pos;
    uint8_t status;	
    if(len == 0)
    {
        return I2C_BADPARA;
    }
    if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_BUSY))
    {
		return I2C_BUSY;
	}	
    if(Set == I2C_GetStatus(pstcI2Cx, I2C_SR_NACKF))//启动I2C前先清除上一次读写失败的NAK标志，否则无法写数据
	{
		I2C_ClearStatus(pstcI2Cx,I2C_CLR_NACKFCLR);
	}
	 status = bsp_i2c_start(pstcI2Cx);
#ifndef AUTOACK	
	pstcI2Cx->CR3_f.FACKEN = 1;//非自动写ACK
#endif	    
    if(status != I2C_RET_OK)
    {
        return status;
    }
	status = bsp_i2c_senddevaddr(pstcI2Cx,(DeviceAddr<<1)|0x01);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_Recdata(pstcI2Cx,data,len);
    if(status != I2C_RET_OK)
    {
        return status;
    }
    status = bsp_i2c_stop(pstcI2Cx);
    if(status != I2C_RET_OK)
    {
        return status;
    }
	return I2C_RET_OK;
}
